package com.kclmedu.springsecuritynodb.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

/*************
 * 安全框架配置类，继承于 WebSecurityConfigurerAdapter 类，只需要重写你感兴趣的方法
 */

@EnableWebSecurity //开启 Web Security 功能，注解的类型继承于 WebSecurityConfigurerAdapter
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private final Logger logger = LoggerFactory.getLogger(SecurityConfig.class);

    /**********
     * Spring Security 5.x开始，密码必需要进行加密，之前的默认是可以不加密的
     * @return
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        //
        logger.debug("-- 进入passwordEncoder 的方法，创建 PasswordEncoder 的实例");
        return new BCryptPasswordEncoder();
    }
    /************
     * 配置认证管理的规则，此处我们采用内存用户名和密码进行认证
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        logger.debug("---> 进入了configure(AuthenticationManagerBuilder) 方法中");
        //添加内存用户
        auth.inMemoryAuthentication()
                .withUser("user")
                .password(passwordEncoder().encode("123456")).roles("USER")
                .and()
                //指定用户名和密码，密码需要使用passwordEncoder进行加密，然后，把此用户添加到哪些角色中
                .withUser("admin")
                .password(passwordEncoder().encode("admin")).roles("ADMIN","USER");
    }

    /************************
     * 指定哪些请求会被安全认证框架所拦截
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        logger.debug("-->进入 configure(HttpSecurity)方法...");
        //配置哪些请求会进入安全认证
        http.authorizeRequests()
                    //添加对不同资源认证过滤, 这些是资源URL 与 角色的对应关系，拥有某个角色就可以访问指定的匹配资源
                    .antMatchers("/index").hasRole("USER")
                    .antMatchers("/admin/**").hasRole("ADMIN")
                    .anyRequest().authenticated()
                    .and()
                    .formLogin()
                    .and()
                    .httpBasic();
    }
}
